#include"li_tasks.h"

volatile uint32_t front, rear;
Tasks_def tasks_[Tasks_LEN];
uint32_t __li_tasks_error_count = 0;
void addTask_(Tasks_def task)
{
	tasks_[rear++] = task;
	if (rear >= Tasks_LEN)
		rear = 0;
#ifdef in_debug
	if (rear == front)
	{
		__li_tasks_error_count++;
		return;
	}
#endif // in_debug
}

void endTask_(Tasks_def task) //trash
{
	int32_t i;
	for (i = front; i != rear;)
	{
		if (tasks_[i] == task)
			break;
		i++;
		if (i == Tasks_LEN)
			i = 0;
	}
	if (i == rear)
		return;
	int32_t j = i, next;
	while (j != rear)
	{
		next = j + 1;
		if (next == Tasks_LEN)
			next = 0;
		tasks_[j] = tasks_[next];
		j = next;
	}
}
void endTaskAt_(char index)
{
	int32_t j = index, next;
	while (j != rear)
	{
		next = j + 1;
		if (next == Tasks_LEN)
			next = 0;
		tasks_[j] = tasks_[next];
		j = next;
	}
}
uint32_t hadTask_(Tasks_def task)
{
	uint32_t  b = 0;
	uint32_t  i;

	for (i = front; i != rear;)
	{
		if (tasks_[i] == task)
		{
			b = i;
			break;
		}

		if (++i == Tasks_LEN)
			i = 0;
	}
	return b;
}


void run_tasks()
{
	int32_t i;
	while (1)
	{
		i = rear;
		while (front != i)
		{
			if (!tasks_[front])
			{
				if (++front >= Tasks_LEN)
					front = 0;
				continue;
			}
			if (tasks_[front]() == 1)
			{
				tasks_[rear++] = tasks_[front];
				if (rear >= Tasks_LEN)
					rear = 0;
			}
			if (++front == Tasks_LEN)
				front = 0;
		}
	}
}

#define queue_len 16
static TasksArg_def fs_arg[queue_len];
static void* args[queue_len];
static char queue_front = 0, queue_back = 0;
int32_t delegate_task_for_args(void);
void addTaskArg(TasksArg_def f, void* arg)
{
	if (f == NULL)
	{
		return;
	}
	fs_arg[(int32_t)queue_back] = f;
	args[(int32_t)queue_back++] = arg;
	if (queue_back >= queue_len)
		queue_back = 0;
	if (!hadTask_(delegate_task_for_args))
		addTask_(delegate_task_for_args);
	if (queue_back == queue_front)
	{
		__li_tasks_error_count++;
		return;
	}
}

int32_t delegate_task_for_args()
{
	static int32_t code;
	TasksArg_def f = fs_arg[(int32_t)queue_front];
	void* a = args[(int32_t)queue_front];
	code = f(a);
	if (code <= 0)
	{
		queue_front++;
		if (queue_front >= queue_len)
			queue_front = 0;
	}
	if (queue_back == queue_front)
		return 0;
	return 1;
}
